home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / quicktime vr / vrscript / feature files / vr3dobjects.c next >
Encoding:
Text File  |  2000-06-23  |  46.4 KB  |  1,590 lines

  1. //////////
  2. //
  3. //    File:        VR3DObjects.c
  4. //
  5. //    Contains:    QuickDraw 3D support for QuickTime VR movies.
  6. //
  7. //    Written by:    Tim Monroe
  8. //                Parts modeled on BoxMoov code by Nick Thompson, Rick Evans, and Robert Dierkes
  9. //                and on code in QD3D book (by yours truly!).
  10. //
  11. //    Copyright:    © 1996-1997 by Apple Computer, Inc., all rights reserved.
  12. //
  13. //    Change History (most recent first):Q3InteractiveRenderer_
  14. //
  15. //       <35>         09/28/98    rtm        added Q3InteractiveRenderer_ calls to VR3DObjects_CreateView
  16. //       <34>         04/22/98    rtm        used GetGWorldPixMap instead of gw->portPixMap in VR3DObjects_PrescreenRoutine
  17. //       <33>         03/18/98    rtm        minor cleanup to make things a little more structured
  18. //       <32>         03/09/98    rtm        removed VR3DObjects_GetEmbeddedPicture; moved code into VR3DTexture.c from
  19. //                                    VR3DObjects_LoadEmbeddedMovie and VR3DObjects_LoopEmbeddedMovie
  20. //       <31>         02/19/98    rtm        changed default chroma key color to prevent transparency problems
  21. //       <30>         01/28/98    rtm        changed NewGWorld calls to QTNewGWorld
  22. //       <29>         01/27/98    rtm        fixed pixel depth problems: QD3D's GWorlds should all be 32-bit
  23. //       <28>         10/13/97    rtm        added VR3DObjects_CreateDefaultGroup call to VR3DObjects_GetModelFromFile
  24. //                                    to provide default lighting for 3DMF files
  25. //       <27>         10/03/97    rtm        removed UPDATE_GWORLD_BROKEN symbol
  26. //       <26>         09/23/97    rtm        added endian adjustment to VR3DObjects_GetEmbeddedPicture
  27. //       <25>         09/15/97    rtm        added UPDATE_GWORLD_BROKEN symbol; should be removed later
  28. //                                    when UpdateGWorld is fixed
  29. //       <24>         09/12/97    rtm        added Windows support to VR3DObjects_GetModelFromFile
  30. //       <23>         07/17/97    rtm        added VR3DObjects_DoIdle
  31. //       <22>         05/05/97    rtm        more work on geometry specifications;
  32. //                                    added Set calls for styles, colors, etc.
  33. //       <21>         05/04/97    rtm        reworked geometry specifications; added Enlist_ functions
  34. //       <20>         05/02/97    rtm        made sound in texture movies directional
  35. //       <19>         04/10/97    rtm        added call to Q3View_Sync to prevent tearing
  36. //       <18>         04/02/97    rtm        copied file for integration with VRScript;
  37. //                                    removed support for object nodes
  38. //       <17>         02/21/97    rtm        added support for multi-node, mixed-type movies;
  39. //                                    fixed window resizing for object nodes
  40. //       <16>         02/10/97    rtm        fixed up vector; fixed pan/tilt granularity in object nodes
  41. //                                    (now QD3D camera doesn't update until object view changes)
  42. //       <15>         02/04/97    rtm        begun implementing support for object nodes
  43. //       <14>         01/24/97    rtm        slight adjustment to camera-setting algorithm
  44. //       <13>         01/23/97    rtm        reworked camera-setting algorithm; now it works fine!
  45. //                                    (replaced VR3DObjects_RotateCamera[XY] with VR3DObjects_SetCamera)
  46. //       <12>         01/20/97    rtm        various small tweaks; nothing major 
  47. //       <11>         01/17/97    rtm        further work on tilting; still unable to fix it entirely 
  48. //       <10>         01/16/97    rtm        added VR3DObjects_SetCameraAspectRatio 
  49. //                                    and VR3DObjects_UpdateDrawContext to handle window resizing
  50. //       <9>         01/14/97    rtm        added polyhedron object to VR3DObjects_CreateModel
  51. //                                    added static texture support
  52. //       <8>         01/13/97    rtm        added some object types to VR3DObjects_CreateModel
  53. //       <7>         01/10/97    rtm        added VR3DObjects_MCActionFilterProc
  54. //                                    (later merged into ApplicationMCActionFilterProc)
  55. //       <6>         01/09/97    rtm        fixed jittering on pan/tilt/zoom;
  56. //                                    fixed VR3DObjects_RotateCameraX for correct tilting
  57. //       <5>         01/03/97    rtm        added animation (that is, rotation) support for 3D objects
  58. //       <4>         12/23/96    rtm        further work on 3D overlay; fixed some jitters
  59. //       <3>         12/20/96    rtm        added zooming support;
  60. //                                    implemented 3D overlay instead of 3D test window
  61. //       <2>         12/16/96    rtm        added 3D test window, intercept procedure
  62. //                                    added QuickTime movie texture mapping support
  63. //       <1>         12/13/96    rtm        first file
  64. //       
  65. //
  66. // This file provides functions to display 3D objects at specific locations in a panorama.
  67. //
  68. // Our strategy: QuickDraw 3D is a "slave" to VR: whenever the VR environment changes,
  69. // we change the QuickDraw 3D camera accordingly and render a new image to our view.
  70. // All this occurs in the prescreen buffer imaging complete procedure.
  71. //
  72. //////////
  73.  
  74. // TODO:
  75. //    + add lighting calls (create new light, move light, set light color/intensity etc.)
  76.  
  77. #if QD3D_AVAIL
  78.  
  79. // header files
  80. #include "VR3DObjects.h"
  81. #include "QTVRUtilities.h"
  82.  
  83. // system headers
  84. #include <QuickDraw.h>
  85. #include <MacWindows.h>
  86. #include <Resources.h>
  87. #include <CodeFragments.h>
  88. #include <Endian.h>
  89.  
  90. // global variables
  91. extern Boolean            gHasQuickDraw3D;                            // is QuickDraw 3D available?
  92. extern Boolean            gHasQuickDraw3D15;                            // is QuickDraw 3D version 1.5 (or greater) available?
  93.  
  94. // constants
  95. const TQ3Point3D        kCameraOrigin = {0.0, 0.0, 0.0};
  96. const TQ3Point3D        kPointOfInterest = {0.0, 0.0, -1000.0};
  97. const TQ3ColorRGB        k3DObjColor = {0.5, 0.5, 0.5};                // default 3D object color
  98. const RGBColor            k3DChromaColor = {0x1111, 0x2222, 0x3333};    // the default chroma key color
  99.  
  100.  
  101. //////////
  102. //
  103. // VR3DObjects_Init
  104. // Initialize for QuickDraw 3D.
  105. //
  106. //////////
  107.  
  108. void VR3DObjects_Init (void)
  109. {
  110.     // make sure that QuickDraw 3D is available
  111.     gHasQuickDraw3D = VR3DObjects_IsQD3DAvailable() ? true : false;
  112.     
  113.     // now perform any initialization
  114.     if (gHasQuickDraw3D) {
  115.         unsigned long        myMajor, myMinor;
  116.         
  117.         Q3Initialize();
  118.         
  119.         // see which version of QD3D is installed; version 1.5 provides some useful new geometries
  120.         Q3GetVersion(&myMajor, &myMinor);
  121.         gHasQuickDraw3D15 = ((myMajor >= 0x0001) && (myMinor >= 0x0005));
  122.     }
  123. }
  124.  
  125.  
  126. //////////
  127. //
  128. // VR3DObjects_Stop
  129. // Clean up for QuickDraw 3D.
  130. //
  131. //////////
  132.  
  133. void VR3DObjects_Stop (void)
  134. {
  135.     // perform any QD3D-related shutdown operations
  136.     if (gHasQuickDraw3D)
  137.         Q3Exit();
  138. }
  139.  
  140.  
  141. //////////
  142. //
  143. // VR3DObjects_IsQD3DAvailable
  144. // Is QuickDraw 3D available in the present operating environment?
  145. //
  146. //////////
  147.  
  148. Boolean VR3DObjects_IsQD3DAvailable (void)
  149. {
  150. #if TARGET_OS_MAC
  151.     return((Ptr)Q3Initialize != (Ptr)kUnresolvedCFragSymbolAddress);
  152. #endif
  153.  
  154. #if TARGET_OS_WIN32
  155.     return(true);
  156. #endif
  157.  
  158.     // the following code should work cross-platform, but currently it returns -5551 (gestaltUndefSelectorErr) on Windows
  159. //    Boolean     myQD3DAvail = false;
  160. //    long        myAttrs;
  161. //    OSErr         myErr = noErr;
  162. //
  163. //    myErr = Gestalt(gestaltQD3D, &myAttrs);
  164. //    if (myErr == noErr)
  165. //        if (myAttrs & (1L << gestaltQD3DPresent))
  166. //            myQD3DAvail = true;
  167. //
  168. //    return(myQD3DAvail);
  169. }
  170.  
  171.  
  172. //////////
  173. //
  174. // VR3DObjects_InitWindowData
  175. // Initialize the window-specific 3D data.
  176. //
  177. //////////
  178.  
  179. void VR3DObjects_InitWindowData (WindowObject theWindowObject)
  180. {
  181.     ApplicationDataHdl    myAppData;
  182.     Rect                myRect;
  183.     OSErr                myErr = noErr;
  184.     
  185.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  186.     if (myAppData != NULL) {
  187.     
  188.         // lock the application data handle
  189.         HLock((Handle)myAppData);
  190.         
  191.         // get the size of the destination window
  192.         if ((**theWindowObject).fMovie != NULL)
  193.             GetMovieBox((**theWindowObject).fMovie, &myRect);
  194.                 
  195.         // create an offscreen GWorld that is the size of the window area
  196.         // (this GWorld is our draw context buffer)
  197.         myErr = QTNewGWorld(&(**myAppData).fQD3DDCGWorld, kOffscreenPixelType, &myRect, NULL, NULL, kICMTempThenAppMemory);
  198.         if (myErr != noErr)
  199.             goto bail;
  200.  
  201.         // create a new view attached to the offscreen GWorld
  202.         (**myAppData).fView = VR3DObjects_CreateView((**myAppData).fQD3DDCGWorld);
  203.         
  204.         // set the FOV vertical orientation flag to ON
  205.         (**myAppData).fQD3DFOVIsVert = true;
  206.  
  207.         // set the default 3D chroma key color
  208.         (**myAppData).fQD3DKeyColor = k3DChromaColor;
  209.  
  210.         // initialize QD3D camera's aspect ratio                                 
  211.         VR3DObjects_SetCameraAspectRatio(theWindowObject);                                 
  212.  
  213.         // initialize QD3D camera's point-of-interest and FOV
  214.         VR3DObjects_SetCamera(theWindowObject);
  215.         
  216. bail:
  217.         // unlock the application data handle
  218.         HUnlock((Handle)myAppData);
  219.     }
  220. }
  221.  
  222.  
  223. //////////
  224. //
  225. // VR3DObjects_DumpWindowData
  226. // Dump the window-specific 3D data.
  227. //
  228. //////////
  229.  
  230. void VR3DObjects_DumpWindowData (WindowObject theWindowObject)
  231. {
  232.     ApplicationDataHdl    myAppData;
  233.     
  234.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  235.     if (myAppData != NULL) {
  236.     
  237.         // dispose of the view object
  238.         if ((**myAppData).fView)
  239.             Q3Object_Dispose((**myAppData).fView);
  240.  
  241.         // dispose of GWorld used by this window object
  242.         if ((**myAppData).fQD3DDCGWorld != NULL)
  243.             DisposeGWorld((**myAppData).fQD3DDCGWorld);
  244.     }
  245. }
  246.  
  247.  
  248. //////////
  249. //
  250. // VR3DObjects_DoIdle
  251. // Do any 3D-related processing that can or should occur at idle time.
  252. // Returns true if the caller should call QTVRUpdate, false otherwise.
  253. //
  254. //////////
  255.  
  256. Boolean VR3DObjects_DoIdle (WindowObject theWindowObject)
  257. {
  258.     ApplicationDataHdl        myAppData;
  259.     VRScript3DObjPtr        myPointer;
  260.     Boolean                    myNeedUpdate = false;
  261.  
  262.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  263.     if (myAppData == NULL)
  264.         return(myNeedUpdate);
  265.     
  266.     // if any currently visible 3D object is animated or has a movie texture,
  267.     // we need to update window
  268.     myPointer = (VRScript3DObjPtr)(**myAppData).fListArray[kVREntry_QD3DObject];
  269.     while ((myPointer != NULL) && !myNeedUpdate) {
  270.         if (myPointer->fModelIsVisible)
  271.             if ((myPointer->fModelIsAnimated) || (myPointer->fTextureIsMovie))
  272.                 myNeedUpdate = true;
  273.         
  274.         myPointer = myPointer->fNextEntry;
  275.     }
  276.  
  277.     return(myNeedUpdate);
  278. }
  279.         
  280.                 
  281. //////////
  282. //
  283. // VR3DObjects_EnlistBox
  284. // Add a box to the list of 3D objects.
  285. //
  286. //////////
  287.  
  288. void VR3DObjects_EnlistBox (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theXSize, float theYSize, float theZSize, UInt32 theOptions)
  289. {
  290.     TQ3BoxData                myBoxData;
  291.     TQ3GeometryObject        myObject;
  292.     TQ3GroupObject            myGroup;
  293.     
  294.     myBoxData.boxAttributeSet = NULL;
  295.     myBoxData.faceAttributeSet = NULL;
  296.     Q3Point3D_Set(&myBoxData.origin, theXSize / -2.0, theYSize / -2.0, theZSize / -2.0);
  297.     Q3Vector3D_Set(&myBoxData.orientation, 0.0, theYSize, 0.0);
  298.     Q3Vector3D_Set(&myBoxData.majorAxis, 0.0, 0.0, theZSize);    
  299.     Q3Vector3D_Set(&myBoxData.minorAxis, theXSize, 0.0, 0.0);    
  300.     myObject = Q3Box_New(&myBoxData);    
  301.     if (myObject != NULL) {
  302.         myGroup = VR3DObjects_CreateDefaultGroup(myObject);
  303.         if (myGroup != NULL)
  304.             VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions);
  305.     }
  306. }
  307.  
  308.  
  309. //////////
  310. //
  311. // VR3DObjects_EnlistCone
  312. // Add a cone to the list of 3D objects.
  313. //
  314. //////////
  315.  
  316. void VR3DObjects_EnlistCone (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, UInt32 theOptions)
  317. {
  318.     TQ3ConeData                myConeData;
  319.     TQ3GeometryObject        myObject;
  320.     TQ3GroupObject            myGroup;
  321.     
  322.     myConeData.coneAttributeSet = NULL;
  323.     myConeData.interiorAttributeSet = NULL;
  324.     myConeData.faceAttributeSet = NULL;
  325.     myConeData.bottomAttributeSet = NULL;
  326.     myConeData.caps = kQ3EndCapMaskBottom;
  327.     Q3Point3D_Set(&myConeData.origin, 0.0, theHeight / -2.0, 0.0);
  328.     Q3Vector3D_Set(&myConeData.orientation, 0.0, theHeight, 0.0);
  329.     Q3Vector3D_Set(&myConeData.majorRadius, 0.0, 0.0, theMajRad);    
  330.     Q3Vector3D_Set(&myConeData.minorRadius, theMinRad, 0.0, 0.0);    
  331.     myObject = Q3Cone_New(&myConeData);
  332.  
  333.     if (myObject != NULL) {
  334.         myGroup = VR3DObjects_CreateDefaultGroup(myObject);
  335.         if (myGroup != NULL) {
  336.             VR3DObjects_SetSubdivisionStyle(myGroup, 20);    // set a finer subdivision style
  337.             VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions);
  338.         }
  339.     }
  340. }
  341.  
  342.  
  343. //////////
  344. //
  345. // VR3DObjects_EnlistCylinder
  346. // Add a cylinder to the list of 3D objects.
  347. //
  348. //////////
  349.  
  350. void VR3DObjects_EnlistCylinder (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, UInt32 theOptions)
  351. {
  352.     TQ3CylinderData            myCylinderData;
  353.     TQ3GeometryObject        myObject;
  354.     TQ3GroupObject            myGroup;
  355.     
  356.     myCylinderData.cylinderAttributeSet = NULL;
  357.     myCylinderData.interiorAttributeSet = NULL;
  358.     myCylinderData.topAttributeSet = NULL;
  359.     myCylinderData.faceAttributeSet = NULL;
  360.     myCylinderData.bottomAttributeSet = NULL;
  361.     myCylinderData.caps = kQ3EndCapMaskTop | kQ3EndCapMaskBottom;
  362.     Q3Point3D_Set(&myCylinderData.origin, 0.0, theHeight / -2.0, 0.0);
  363.     Q3Vector3D_Set(&myCylinderData.orientation, 0.0, theHeight, 0.0);
  364.     Q3Vector3D_Set(&myCylinderData.majorRadius, 0.0, 0.0, theMajRad);    
  365.     Q3Vector3D_Set(&myCylinderData.minorRadius, theMinRad, 0.0, 0.0);    
  366.     myObject = Q3Cylinder_New(&myCylinderData);
  367.     
  368.     if (myObject != NULL) {
  369.         myGroup = VR3DObjects_CreateDefaultGroup(myObject);
  370.         if (myGroup != NULL) {
  371.             VR3DObjects_SetSubdivisionStyle(myGroup, 20);    // set a finer subdivision style
  372.             VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions);
  373.         }
  374.     }
  375. }
  376.  
  377.  
  378. //////////
  379. //
  380. // VR3DObjects_EnlistEllipsoid
  381. // Add an ellipsoid to the list of 3D objects.
  382. //
  383. //////////
  384.  
  385. void VR3DObjects_EnlistEllipsoid (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, UInt32 theOptions)
  386. {
  387.     TQ3EllipsoidData        myEllipsoidData;
  388.     TQ3GeometryObject        myObject;
  389.     TQ3GroupObject            myGroup;
  390.     
  391.     myEllipsoidData.ellipsoidAttributeSet = NULL;
  392.     myEllipsoidData.interiorAttributeSet = NULL;
  393.     myEllipsoidData.caps = 0L;
  394.     Q3Point3D_Set(&myEllipsoidData.origin, 0.0, 0.0, 0.0);
  395.     Q3Vector3D_Set(&myEllipsoidData.orientation, 0.0, theHeight, 0.0);
  396.     Q3Vector3D_Set(&myEllipsoidData.majorRadius, 0.0, 0.0, theMajRad);    
  397.     Q3Vector3D_Set(&myEllipsoidData.minorRadius, theMinRad, 0.0, 0.0);    
  398.     myObject = Q3Ellipsoid_New(&myEllipsoidData);
  399.  
  400.     if (myObject != NULL) {
  401.         myGroup = VR3DObjects_CreateDefaultGroup(myObject);
  402.         if (myGroup != NULL) {
  403.             VR3DObjects_SetSubdivisionStyle(myGroup, 20);    // set a finer subdivision style
  404.             VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions);
  405.         }
  406.     }
  407. }
  408.  
  409.  
  410. //////////
  411. //
  412. // VR3DObjects_EnlistTorus
  413. // Add a torus to the list of 3D objects.
  414. //
  415. //////////
  416.  
  417. void VR3DObjects_EnlistTorus (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, float theMajRad, float theMinRad, float theHeight, float theRatio, UInt32 theOptions)
  418. {
  419.     TQ3TorusData            myTorusData;
  420.     TQ3GeometryObject        myObject;
  421.     TQ3GroupObject            myGroup;
  422.     
  423.     myTorusData.torusAttributeSet = NULL;
  424.     myTorusData.interiorAttributeSet = NULL;
  425.     myTorusData.caps = 0L;
  426.     myTorusData.ratio = theRatio;
  427.     Q3Point3D_Set(&myTorusData.origin, 0.0, 0.0, 0.0);
  428.     Q3Vector3D_Set(&myTorusData.orientation, 0.0, theHeight, 0.0);
  429.     Q3Vector3D_Set(&myTorusData.majorRadius, 0.0, 0.0, theMajRad);    
  430.     Q3Vector3D_Set(&myTorusData.minorRadius, theMinRad, 0.0, 0.0);    
  431.     myObject = Q3Torus_New(&myTorusData);
  432.  
  433.     if (myObject != NULL) {
  434.         myGroup = VR3DObjects_CreateDefaultGroup(myObject);
  435.         if (myGroup != NULL) {
  436.             VR3DObjects_SetSubdivisionStyle(myGroup, 20);    // set a finer subdivision style
  437.             VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions);
  438.         }
  439.     }
  440. }
  441.  
  442.  
  443. //////////
  444. //
  445. // VR3DObjects_EnlistRectangle
  446. // Add a rectangle to the list of 3D objects.
  447. // This is intended to serve as a "screen" for texture-mapped movies or pictures.
  448. //
  449. //////////
  450.  
  451. void VR3DObjects_EnlistRectangle (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ,
  452.                                     float theX1, float theY1, float theZ1, 
  453.                                     float theX2, float theY2, float theZ2, 
  454.                                     float theX3, float theY3, float theZ3, 
  455.                                     float theX4, float theY4, float theZ4, UInt32 theOptions)
  456. {
  457.     TQ3PolyhedronData            myPolyData;
  458.     static TQ3Vertex3D            myVertices[4];
  459.     static TQ3Param2D            myUVParams[4] = {
  460.                                     {0.0, 0.0},
  461.                                     {0.0, 1.0},
  462.                                     {1.0, 1.0},
  463.                                     {1.0, 0.0}
  464.                                 };
  465.     
  466.     TQ3PolyhedronTriangleData    myTriangles[2] = {
  467.                                     { { 0, 1, 3 }, kQ3PolyhedronEdge01 | kQ3PolyhedronEdge20, NULL },
  468.                                     { { 1, 2, 3 }, kQ3PolyhedronEdge01 | kQ3PolyhedronEdge12, NULL }
  469.                                 };
  470.  
  471.     short                        myIndex;
  472.     TQ3GeometryObject            myObject;
  473.     TQ3GroupObject                myGroup;
  474.     
  475.     // set up vertices, edges, and triangular faces
  476.     Q3Point3D_Set(&myVertices[0].point, theX1, theY1, theZ1);
  477.     Q3Point3D_Set(&myVertices[1].point, theX2, theY2, theZ2);
  478.     Q3Point3D_Set(&myVertices[2].point, theX3, theY3, theZ3);
  479.     Q3Point3D_Set(&myVertices[3].point, theX4, theY4, theZ4);
  480.     myVertices[0].attributeSet = NULL;
  481.     myVertices[1].attributeSet = NULL;
  482.     myVertices[2].attributeSet = NULL;
  483.     myVertices[3].attributeSet = NULL;
  484.     myPolyData.numVertices = 4;
  485.     myPolyData.vertices = myVertices;    
  486.     myPolyData.numEdges = 0;
  487.     myPolyData.edges = NULL;
  488.     myPolyData.numTriangles    = 2;
  489.     myPolyData.triangles = myTriangles;
  490.     
  491.     // add uv parameterization to the polyhedron
  492.     for (myIndex = 0; myIndex < myPolyData.numVertices; myIndex++) {                    
  493.         myVertices[myIndex].attributeSet = Q3AttributeSet_New();
  494.         Q3AttributeSet_Add(myVertices[myIndex].attributeSet, kQ3AttributeTypeSurfaceUV, &myUVParams[myIndex]);
  495.     }
  496.     
  497.     myPolyData.polyhedronAttributeSet = Q3AttributeSet_New();
  498.     Q3AttributeSet_Add(myPolyData.polyhedronAttributeSet, kQ3AttributeTypeDiffuseColor, &k3DObjColor);
  499.  
  500.     myObject = Q3Polyhedron_New(&myPolyData);
  501.  
  502.     if (myObject != NULL) {
  503.         myGroup = VR3DObjects_CreateDefaultGroup(myObject);
  504.         if (myGroup != NULL)
  505.             VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions);
  506.     }
  507. }
  508.  
  509.  
  510. //////////
  511. //
  512. // VR3DObjects_Enlist3DMFFile
  513. // Open a 3DMF file and add it to the list of 3D objects.
  514. //
  515. //////////
  516.  
  517. void VR3DObjects_Enlist3DMFFile (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, UInt32 theOptions, char *thePathName)
  518. {
  519.     TQ3GroupObject            myGroup;
  520.     
  521.     myGroup = VR3DObjects_GetModelFromFile(thePathName);
  522.     if (myGroup != NULL) 
  523.         VRScript_Enlist3DObject(theWindowObject, myGroup, theEntryID, theX, theY, theZ, theOptions);
  524. }
  525.  
  526.  
  527. //////////
  528. //
  529. // VR3DObjects_CreateDefaultGroup
  530. // Return a default model containing the specified object.
  531. //
  532. //////////
  533.  
  534. TQ3GroupObject VR3DObjects_CreateDefaultGroup (TQ3GeometryObject theObject)
  535. {
  536.     TQ3GroupObject            myGroup;
  537.     
  538.     // create a new display group
  539.     myGroup = Q3DisplayGroup_New();
  540.     if (myGroup != NULL) {
  541.         TQ3ShaderObject            myIlluminationShader;
  542.         
  543.         // create an illumination shader    
  544.         myIlluminationShader = Q3PhongIllumination_New();
  545.         if (myIlluminationShader != NULL) {
  546.             TQ3AttributeSet            myAttributeSet;
  547.  
  548.             // add the illumination shader to our display group    
  549.             Q3Group_AddObject(myGroup, myIlluminationShader);
  550.             
  551.             // add the default diffuse color to the group
  552.             myAttributeSet = Q3AttributeSet_New();
  553.             Q3AttributeSet_Add(myAttributeSet, kQ3AttributeTypeDiffuseColor, &k3DObjColor);
  554.             Q3Group_AddObject(myGroup, myAttributeSet);
  555.  
  556.             // add the geometry object to the group
  557.             Q3Group_AddObject(myGroup, theObject);
  558.             
  559.             // dispose of the objects we've added to the group
  560.             if (myIlluminationShader != NULL) 
  561.                 Q3Object_Dispose(myIlluminationShader);    
  562.         }
  563.     }
  564.     
  565.     if (theObject != NULL) 
  566.         Q3Object_Dispose(theObject);
  567.     
  568.     return(myGroup);
  569. }
  570.  
  571.  
  572. //////////
  573. //
  574. // VR3DObjects_CreateView
  575. // Return a view object for the QD3D objects in our model.
  576. //
  577. //////////
  578.  
  579. TQ3ViewObject VR3DObjects_CreateView (GWorldPtr theGWorld)
  580. {
  581.     TQ3Status                myStatus;
  582.     TQ3ViewObject            myView;
  583.     TQ3DrawContextObject    myDrawContext;
  584.     TQ3RendererObject        myRenderer;
  585.     TQ3CameraObject            myCamera;
  586.     TQ3GroupObject            myLights;
  587.     
  588.     // create a new view object
  589.     myView = Q3View_New();
  590.     if (myView == NULL)
  591.         goto bail;
  592.     
  593.     // create and set draw context
  594.     myDrawContext = VR3DObjects_CreateDrawContext(theGWorld);
  595.     if (myDrawContext == NULL)
  596.         goto bail;
  597.         
  598.     myStatus = Q3View_SetDrawContext(myView, myDrawContext);
  599.     if (myStatus == kQ3Failure)
  600.         goto bail;
  601.  
  602.     Q3Object_Dispose(myDrawContext);
  603.     
  604.     // create and set renderer
  605.     myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeInteractive);
  606.     if (myRenderer == NULL) {
  607.         myRenderer = Q3Renderer_NewFromType(kQ3RendererTypeWireFrame);
  608.     } else {
  609.         // these two lines allow us to use the best possible renderer,
  610.         // including hardware if it is installed.
  611.         Q3InteractiveRenderer_SetDoubleBufferBypass(myRenderer, kQ3True);                        
  612.         Q3InteractiveRenderer_SetPreferences(myRenderer, kQAVendor_BestChoice, 0);
  613.     }
  614.         
  615.     if (myRenderer == NULL) 
  616.         goto bail;
  617.     
  618.     myStatus = Q3View_SetRenderer(myView, myRenderer);
  619.     if (myStatus == kQ3Failure)
  620.         goto bail;
  621.         
  622.     Q3Object_Dispose(myRenderer);
  623.     
  624.     // create and set camera
  625.     myCamera = VR3DObjects_CreateCamera(theGWorld);
  626.     if (myCamera == NULL)
  627.         goto bail;
  628.         
  629.     myStatus = Q3View_SetCamera(myView, myCamera);
  630.     if (myStatus == kQ3Failure)
  631.         goto bail;
  632.  
  633.     Q3Object_Dispose(myCamera);
  634.     
  635.     // create and set lights
  636.     myLights = VR3DObjects_CreateLights();
  637.     if (myLights == NULL)
  638.         goto bail;
  639.         
  640.     myStatus = Q3View_SetLightGroup(myView, myLights);
  641.     if (myStatus == kQ3Failure)
  642.         goto bail;
  643.  
  644.     Q3Object_Dispose(myLights);
  645.         
  646.     return(myView);
  647.     
  648. bail:
  649.     // if any of the above creations failed, don't return a view
  650.     return(NULL);
  651. }
  652.  
  653.  
  654. //////////
  655. //
  656. // VR3DObjects_CreateLights
  657. // Return a light group object for the QD3D objects in our model.
  658. // For displaying embedded movies, we need just the ambient light.
  659. //
  660. //////////
  661.  
  662. TQ3GroupObject VR3DObjects_CreateLights (void)
  663. {
  664.     TQ3GroupPosition            myGroupPosition;
  665.     TQ3GroupObject                myLightList;
  666.     TQ3LightData                myLightData;
  667.     TQ3PointLightData            myPointLightData;
  668.     TQ3DirectionalLightData        myDirectionalLightData;
  669.     TQ3LightObject                myAmbientLight, myPointLight, myFillLight;
  670.     TQ3Point3D                    myPointLocation =    {-10.0, 0.0, 10.0};
  671.     TQ3Vector3D                    myFillDirection =    {10.0, 0.0, 10.0};
  672.     TQ3ColorRGB                    myWhiteLight =        {1.0F, 1.0F, 1.0F};
  673.     
  674.     // create the ambient light
  675.     myLightData.isOn = kQ3True;
  676.     myLightData.color = myWhiteLight;
  677.     myLightData.brightness = 1.0F;
  678.     myAmbientLight = Q3AmbientLight_New(&myLightData);
  679.     if (myAmbientLight == NULL)
  680.         goto bail;
  681.     
  682.     // create a point light
  683.     myLightData.brightness = 1.0F;
  684.     myPointLightData.lightData = myLightData;
  685.     myPointLightData.castsShadows = kQ3False;
  686.     myPointLightData.attenuation = kQ3AttenuationTypeNone;
  687.     myPointLightData.location = myPointLocation;
  688.     myPointLight = Q3PointLight_New(&myPointLightData);
  689.     if (myPointLight == NULL)
  690.         goto bail;
  691.  
  692.     // create a directional light for fill
  693.     myLightData.brightness = 0.2F;
  694.     myDirectionalLightData.lightData = myLightData;
  695.     myDirectionalLightData.castsShadows = kQ3False;
  696.     myDirectionalLightData.direction = myFillDirection;
  697.     myFillLight = Q3DirectionalLight_New(&myDirectionalLightData);
  698.     if (myFillLight == NULL)
  699.         goto bail;
  700.  
  701.     // create a light group and add each of the lights to the group
  702.     myLightList = Q3LightGroup_New();
  703.     if (myLightList == NULL)
  704.         goto bail;
  705.     myGroupPosition = Q3Group_AddObject(myLightList, myAmbientLight);
  706.     if (myGroupPosition == 0)
  707.         goto bail;
  708.     myGroupPosition = Q3Group_AddObject(myLightList, myPointLight);
  709.     if (myGroupPosition == 0)
  710.         goto bail;
  711.     myGroupPosition = Q3Group_AddObject(myLightList, myFillLight);
  712.     if (myGroupPosition == 0)
  713.         goto bail;
  714.  
  715.     Q3Object_Dispose(myAmbientLight);
  716.     Q3Object_Dispose(myPointLight);
  717.     Q3Object_Dispose(myFillLight);
  718.  
  719.     return(myLightList);
  720.     
  721. bail:
  722.     // if any of the above creations failed, don't return a light group
  723.     return(NULL);
  724. }
  725.  
  726.  
  727. //////////
  728. //
  729. // VR3DObjects_CreateDrawContext
  730. // Return a draw context object for the QD3D objects in our model.
  731. //
  732. //////////
  733.  
  734. TQ3DrawContextObject VR3DObjects_CreateDrawContext (GWorldPtr theGWorld)
  735. {
  736.     TQ3DrawContextObject        myDrawContext;
  737.     TQ3PixmapDrawContextData    myPixMapDrawContextData;
  738.     TQ3DrawContextData            myDrawContextData;
  739.     PixMapHandle                 myPixMap;
  740.     Rect                        myRect;
  741.     TQ3ColorARGB                myClearColor;
  742.     float                        myFactor = 0xffff;
  743.     
  744.     if (theGWorld == NULL)
  745.         goto bail;
  746.         
  747.     // set the background color;
  748.     // note that RGBColor is defined in the range 0-65535,
  749.     // while TQ3ColorARGB is defined in the range 0.0-1.0; hence the division....
  750.     myClearColor.a = 0.0;
  751.     myClearColor.r = k3DChromaColor.red / myFactor;
  752.     myClearColor.g = k3DChromaColor.green / myFactor;
  753.     myClearColor.b = k3DChromaColor.blue / myFactor;
  754.     
  755.     // fill in draw context data
  756.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  757.     myDrawContextData.clearImageColor = myClearColor;
  758.     myDrawContextData.paneState = kQ3False;
  759.     myDrawContextData.maskState = kQ3False;
  760.     myDrawContextData.doubleBufferState = kQ3False;
  761.  
  762.     myPixMapDrawContextData.drawContextData = myDrawContextData;
  763.     
  764.     // the pixmap must remain locked in memory for as long as it exists
  765.     myPixMap = GetGWorldPixMap(theGWorld);
  766.     LockPixels(myPixMap);
  767.  
  768.     myRect = theGWorld->portRect;
  769.     
  770.     myPixMapDrawContextData.pixmap.width = myRect.right - myRect.left;
  771.     myPixMapDrawContextData.pixmap.height = myRect.bottom - myRect.top;
  772.     myPixMapDrawContextData.pixmap.rowBytes = (unsigned long)((**myPixMap).rowBytes & 0x3fff);
  773.     myPixMapDrawContextData.pixmap.pixelType = kQ3PixelTypeRGB32;
  774.     myPixMapDrawContextData.pixmap.pixelSize = 32;
  775.     myPixMapDrawContextData.pixmap.bitOrder = kQ3EndianBig;
  776.     myPixMapDrawContextData.pixmap.byteOrder = kQ3EndianBig;
  777.     myPixMapDrawContextData.pixmap.image = GetPixBaseAddr(myPixMap);
  778.     
  779.     // create draw context and return it
  780.     myDrawContext = Q3PixmapDrawContext_New(&myPixMapDrawContextData);
  781.  
  782. bail:
  783.     return(myDrawContext);
  784. }
  785.  
  786.  
  787. //////////
  788. //
  789. // VR3DObjects_CreateCamera
  790. // Return a camera object for the QD3D objects in our model.
  791. // Note that some of the initial values are wrong and will soon be reset (in InitApplicationWindowObject).
  792. //
  793. //////////
  794.  
  795. TQ3CameraObject VR3DObjects_CreateCamera (CGrafPtr thePort)
  796. {
  797.     TQ3CameraObject                    myCamera;
  798.     TQ3ViewAngleAspectCameraData    myCameraData;
  799.     
  800.     TQ3Point3D                         myFrom         = kCameraOrigin;
  801.     TQ3Point3D                         myTo         = kPointOfInterest;
  802.     TQ3Vector3D                     myUp         = {0.0, 1.0, 0.0};
  803.  
  804.     float                             myFOV        = 1.00;                // initial FOV really depends on QTVR instance, so we reset this later
  805.     float                             myHither    = 0.01;
  806.     float                             myYon         = 1000.0;
  807.     
  808.     myCameraData.cameraData.placement.cameraLocation = myFrom;
  809.     myCameraData.cameraData.placement.pointOfInterest = myTo;
  810.     myCameraData.cameraData.placement.upVector = myUp;
  811.  
  812.     myCameraData.cameraData.range.hither = myHither;
  813.     myCameraData.cameraData.range.yon = myYon;
  814.  
  815.     // the default camera view port
  816.     myCameraData.cameraData.viewPort.origin.x = -1.0F;
  817.     myCameraData.cameraData.viewPort.origin.y = 1.0F;
  818.     myCameraData.cameraData.viewPort.width = 2.0F;
  819.     myCameraData.cameraData.viewPort.height = 2.0F;
  820.     
  821.     // some default FOV and aspect ratio values
  822.     myCameraData.fov = myFOV;
  823.     myCameraData.aspectRatioXToY =
  824.         (float)(thePort->portRect.right - thePort->portRect.left) / 
  825.         (float)(thePort->portRect.bottom - thePort->portRect.top);
  826.         
  827.     myCamera = Q3ViewAngleAspectCamera_New(&myCameraData);
  828.  
  829.     return(myCamera);
  830. }
  831.  
  832.  
  833. //////////
  834. //
  835. // VR3DObjects_GetModelAttributeSet
  836. // Get the attribute set of a 3D model.
  837. //
  838. //////////
  839.  
  840. TQ3AttributeSet VR3DObjects_GetModelAttributeSet (VRScript3DObjPtr thePointer)
  841. {
  842.     TQ3AttributeSet        myAttributeSet = NULL;
  843.     
  844.     if ((thePointer != NULL) && (thePointer->fModel != NULL)) {
  845.         TQ3GroupPosition    myPosition;
  846.         
  847.         // get the position of the attribute set in the group
  848.         Q3Group_GetFirstPositionOfType(thePointer->fModel, kQ3SetTypeAttribute, &myPosition);
  849.         if (myPosition != 0)        // get the attribute set
  850.             Q3Group_GetPositionObject(thePointer->fModel, myPosition, &myAttributeSet);
  851.     }
  852.     
  853.     return(myAttributeSet);
  854. }
  855.  
  856.  
  857. //////////
  858. //
  859. // VR3DObjects_SetSubdivisionStyle
  860. // Create a subdivision style and add it to the specified group.
  861. //
  862. //////////
  863.  
  864. void VR3DObjects_SetSubdivisionStyle (TQ3GroupObject theGroup, short theNumDivisions)
  865. {
  866.     TQ3SubdivisionStyleData        myStyleData;
  867.     TQ3StyleObject                myStyleObject;
  868.     TQ3GroupPosition            myPosition;
  869.     
  870.     // get the position of the geometry object in the group
  871.     Q3Group_GetFirstPositionOfType(theGroup, kQ3ShapeTypeGeometry, &myPosition);
  872.     
  873.     // set a subdivision style
  874.     myStyleData.method = kQ3SubdivisionMethodConstant;
  875.     myStyleData.c1 = theNumDivisions;
  876.     myStyleData.c2 = theNumDivisions;
  877.     myStyleObject = Q3SubdivisionStyle_New(&myStyleData);
  878.     Q3Group_AddObjectBefore(theGroup, myPosition, myStyleObject);
  879.     Q3Object_Dispose(myStyleObject);
  880. }
  881.  
  882.  
  883. //////////
  884. //
  885. // VR3DObjects_SetColor
  886. // Set the diffuse color of a 3D object.
  887. //
  888. //////////
  889.  
  890. void VR3DObjects_SetColor (WindowObject theWindowObject, UInt32 theEntryID, float theRed, float theGreen, float theBlue, UInt32 theOptions)
  891. {
  892. #pragma unused(theOptions)
  893.     VRScript3DObjPtr    myPointer;
  894.     TQ3AttributeSet        myAttributeSet;
  895.     
  896.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  897.     if (myPointer != NULL) {
  898.     
  899.         myAttributeSet = VR3DObjects_GetModelAttributeSet(myPointer);
  900.         if (myAttributeSet != NULL) {
  901.             TQ3ColorRGB                myColor;
  902.             
  903.             // remove the existing diffuse color attribute
  904.             Q3AttributeSet_Clear(myAttributeSet, kQ3AttributeTypeDiffuseColor);
  905.             Q3ColorRGB_Set(&myColor, theRed, theGreen, theBlue);
  906.             Q3AttributeSet_Add(myAttributeSet, kQ3AttributeTypeDiffuseColor, &myColor);
  907.         }
  908.         
  909.         Q3Object_Dispose(myAttributeSet);
  910.     }
  911. }
  912.  
  913.  
  914. //////////
  915. //
  916. // VR3DObjects_SetTransparency
  917. // Set the transparency level of a 3D object.
  918. //
  919. //////////
  920.  
  921. void VR3DObjects_SetTransparency (WindowObject theWindowObject, UInt32 theEntryID, float theRed, float theGreen, float theBlue, UInt32 theOptions)
  922. {
  923. #pragma unused(theOptions)
  924.     VRScript3DObjPtr    myPointer;
  925.     TQ3AttributeSet        myAttributeSet;
  926.     
  927.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  928.     if (myPointer != NULL) {
  929.     
  930.         myAttributeSet = VR3DObjects_GetModelAttributeSet(myPointer);
  931.         if (myAttributeSet != NULL) {
  932.             TQ3ColorRGB                myColor;
  933.             
  934.             // remove the existing transparency color attribute
  935.             Q3AttributeSet_Clear(myAttributeSet, kQ3AttributeTypeTransparencyColor);
  936.             Q3ColorRGB_Set(&myColor, theRed, theGreen, theBlue);
  937.             Q3AttributeSet_Add(myAttributeSet, kQ3AttributeTypeTransparencyColor, &myColor);
  938.         }
  939.         
  940.         Q3Object_Dispose(myAttributeSet);
  941.     }
  942. }
  943.  
  944.  
  945. //////////
  946. //
  947. // VR3DObjects_SetInterpolation
  948. // Set the interpolation style of a 3D object.
  949. //
  950. //////////
  951.  
  952. void VR3DObjects_SetInterpolation (WindowObject theWindowObject, UInt32 theEntryID, UInt32 theStyle, UInt32 theOptions)
  953. {
  954. #pragma unused(theOptions)
  955.     VRScript3DObjPtr    myPointer;
  956.  
  957.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  958.     if (myPointer != NULL) 
  959.         Q3InterpolationStyle_Set(myPointer->fInterpolation, (TQ3InterpolationStyle)theStyle);
  960. }
  961.  
  962.  
  963. //////////
  964. //
  965. // VR3DObjects_SetBackfacing
  966. // Set the backfacing style of a 3D object.
  967. //
  968. //////////
  969.  
  970. void VR3DObjects_SetBackfacing (WindowObject theWindowObject, UInt32 theEntryID, UInt32 theStyle, UInt32 theOptions)
  971. {
  972. #pragma unused(theOptions)
  973.     VRScript3DObjPtr    myPointer;
  974.  
  975.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  976.     if (myPointer != NULL) 
  977.         Q3BackfacingStyle_Set(myPointer->fBackFacing, (TQ3BackfacingStyle)theStyle);
  978. }
  979.  
  980.  
  981. //////////
  982. //
  983. // VR3DObjects_SetFill
  984. // Set the fill style of a 3D object.
  985. //
  986. //////////
  987.  
  988. void VR3DObjects_SetFill (WindowObject theWindowObject, UInt32 theEntryID, UInt32 theStyle, UInt32 theOptions)
  989. {
  990. #pragma unused(theOptions)
  991.     VRScript3DObjPtr    myPointer;
  992.  
  993.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  994.     if (myPointer != NULL) 
  995.         Q3FillStyle_Set(myPointer->fFillStyle, (TQ3FillStyle)theStyle);
  996. }
  997.  
  998.  
  999. //////////
  1000. //
  1001. // VR3DObjects_SetLocation
  1002. // Set the location of a 3D object.
  1003. //
  1004. //////////
  1005.  
  1006. void VR3DObjects_SetLocation (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, UInt32 theOptions)
  1007. {
  1008.     VRScript3DObjPtr    myPointer;
  1009.  
  1010.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  1011.     if (myPointer != NULL) {
  1012.         if (theOptions == kVRValue_Relative) {
  1013.             myPointer->fGroupCenter.x -= theX;
  1014.             myPointer->fGroupCenter.y += theY;
  1015.             myPointer->fGroupCenter.z -= theZ;
  1016.         } else {
  1017.             myPointer->fGroupCenter.x = -1 * theX;
  1018.             myPointer->fGroupCenter.y = theY;
  1019.             myPointer->fGroupCenter.z = -1 * theZ;
  1020.         }
  1021.     }
  1022. }
  1023.  
  1024.  
  1025. //////////
  1026. //
  1027. // VR3DObjects_SetRotation
  1028. // Set the rotation factors of a 3D object.
  1029. //
  1030. //////////
  1031.  
  1032. void VR3DObjects_SetRotation (WindowObject theWindowObject, UInt32 theEntryID, float theX, float theY, float theZ, UInt32 theOptions)
  1033. {
  1034.     VRScript3DObjPtr    myPointer;
  1035.  
  1036.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  1037.     if (myPointer != NULL) {
  1038.         if (theOptions == kVRValue_Relative) {
  1039.             myPointer->fRotateFactors.x += theX;
  1040.             myPointer->fRotateFactors.y += theY;
  1041.             myPointer->fRotateFactors.z += theZ;
  1042.         } else {
  1043.             myPointer->fRotateFactors.x = theX;
  1044.             myPointer->fRotateFactors.y = theY;
  1045.             myPointer->fRotateFactors.z = theZ;
  1046.         }
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. //////////
  1052. //
  1053. // VR3DObjects_SetRotationState
  1054. // Set the rotation state (on or off) of a 3D object.
  1055. //
  1056. //////////
  1057.  
  1058. void VR3DObjects_SetRotationState (WindowObject theWindowObject, UInt32 theEntryID, Boolean theState, UInt32 theOptions)
  1059. {
  1060. #pragma unused(theOptions)
  1061.     VRScript3DObjPtr    myPointer;
  1062.  
  1063.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  1064.     if (myPointer != NULL) {
  1065.         if (theState == kVRState_Toggle)
  1066.             theState = !(myPointer->fModelIsAnimated);
  1067.         myPointer->fModelIsAnimated = theState;
  1068.     }
  1069. }
  1070.  
  1071.  
  1072. //////////
  1073. //
  1074. // VR3DObjects_SetVisibleState
  1075. // Set the visibility state (on or off) of a 3D object.
  1076. //
  1077. //////////
  1078.  
  1079. void VR3DObjects_SetVisibleState (WindowObject theWindowObject, UInt32 theEntryID, Boolean theState, UInt32 theOptions)
  1080. {
  1081. #pragma unused(theOptions)
  1082.     VRScript3DObjPtr    myPointer;
  1083.  
  1084.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  1085.     if (myPointer != NULL) {
  1086.         if (theState == kVRState_Toggle)
  1087.             theState = !(myPointer->fModelIsVisible);
  1088.         myPointer->fModelIsVisible = theState;
  1089.     }
  1090. }
  1091.  
  1092.  
  1093. //////////
  1094. //
  1095. // VR3DObjects_SetTexture
  1096. // Set the texture of a 3D object.
  1097. //
  1098. //////////
  1099.  
  1100. void VR3DObjects_SetTexture (WindowObject theWindowObject, UInt32 theEntryID, Boolean isMovie, UInt32 theOptions, char *thePathName)
  1101. {
  1102. #pragma unused(theOptions)
  1103.  
  1104.     VRScript3DObjPtr    myPointer;
  1105.  
  1106.     myPointer = (VRScript3DObjPtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QD3DObject, theEntryID);
  1107.     if (myPointer != NULL) {
  1108.     
  1109.         // delete any existing texture structure, since we'll soon create another one    
  1110.         if (myPointer->fTexture != NULL) {
  1111.             VR3DTexture_Delete(myPointer->fTexture);
  1112.             myPointer->fTexture = NULL;
  1113.         }
  1114.             
  1115.         myPointer->fTextureIsMovie = isMovie;
  1116.         myPointer->fTexture = VR3DTexture_New(thePathName, isMovie);
  1117.         
  1118.         if (myPointer->fTexture != NULL)
  1119.             VR3DTexture_AddToGroup(myPointer->fTexture, myPointer->fModel);
  1120.     }
  1121. }
  1122.  
  1123.  
  1124. //////////
  1125. //
  1126. // VR3DObjects_AnimateModel
  1127. // Animate the QuickDraw 3D model.
  1128. //
  1129. //////////
  1130.  
  1131. void VR3DObjects_AnimateModel (VRScript3DObjPtr thePointer)
  1132. {
  1133.     TQ3Matrix4x4        myMatrix;
  1134.     TQ3Vector3D            myVector;
  1135.     
  1136.     if (thePointer != NULL) {        
  1137.         // rotate the object around the local x axis
  1138.         Q3Vector3D_Set(&myVector, 1.0, 0.0, 0.0);
  1139.         Q3Matrix4x4_SetRotateAboutAxis(&myMatrix, &(thePointer->fGroupCenter), &myVector, thePointer->fRotateFactors.x);
  1140.         Q3Matrix4x4_Multiply(&(thePointer->fRotation), &myMatrix, &(thePointer->fRotation));
  1141.         
  1142.         // rotate the object around the local y axis
  1143.         Q3Vector3D_Set(&myVector, 0.0, 1.0, 0.0);
  1144.         Q3Matrix4x4_SetRotateAboutAxis(&myMatrix, &(thePointer->fGroupCenter), &myVector, thePointer->fRotateFactors.y);
  1145.         Q3Matrix4x4_Multiply(&(thePointer->fRotation), &myMatrix, &(thePointer->fRotation));
  1146.         
  1147.         // rotate the object around the local z axis
  1148.         Q3Vector3D_Set(&myVector, 0.0, 0.0, 1.0);
  1149.         Q3Matrix4x4_SetRotateAboutAxis(&myMatrix, &(thePointer->fGroupCenter), &myVector, thePointer->fRotateFactors.z);
  1150.         Q3Matrix4x4_Multiply(&(thePointer->fRotation), &myMatrix, &(thePointer->fRotation));
  1151.     }
  1152. }
  1153.  
  1154.  
  1155. //////////
  1156. //
  1157. // VR3DObjects_DrawModel
  1158. // Draw any QuickDraw 3D models into the (offscreen GWorld) pixmap draw context.
  1159. // This routine is called only in the prescreen buffer imaging complete procedure.
  1160. //
  1161. //////////
  1162.  
  1163. TQ3Status VR3DObjects_DrawModel (WindowObject theWindowObject)
  1164. {
  1165.     ApplicationDataHdl    myAppData;
  1166.     TQ3Status            myStatus = kQ3Failure;
  1167.     TQ3ViewObject        myView;
  1168.     VRScript3DObjPtr    myPointer;
  1169.     
  1170.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);    
  1171.     if (myAppData == NULL)
  1172.         return(myStatus);
  1173.     
  1174.     myView = (**myAppData).fView;
  1175.     if (myView == NULL)
  1176.         return(myStatus);
  1177.     
  1178.     // if the camera needs to be updated, do so now
  1179.     if ((**myAppData).fViewHasChanged)
  1180.         VR3DObjects_SetCamera(theWindowObject);
  1181.  
  1182.     // our rendering loop
  1183.     myStatus = Q3View_StartRendering(myView);
  1184.     if (myStatus != kQ3Failure)
  1185.         do {
  1186.             // walk our linked list of 3D objects and render any visible objects,
  1187.             // after updating any object-specific properties 
  1188.             myPointer = (VRScript3DObjPtr)(**myAppData).fListArray[kVREntry_QD3DObject];
  1189.             while (myPointer != NULL) {
  1190.                 if (myPointer->fModelIsVisible) {
  1191.                     // if there is an active movie texture, advance the movie to the next frame
  1192.                     if (myPointer->fTexture)
  1193.                         if (myPointer->fTextureIsMovie)
  1194.                             VR3DTexture_NextFrame(myPointer->fTexture);
  1195.                     
  1196.                     // if animation is active, animate the model
  1197.                     if (myPointer->fModelIsAnimated)
  1198.                         VR3DObjects_AnimateModel(myPointer);
  1199.                         
  1200.                     // submit the model
  1201.                     Q3Push_Submit(myView);
  1202.                     VR3DObjects_SubmitModel(myPointer, myView);
  1203.                     Q3Pop_Submit(myView);
  1204.                 }
  1205.                 
  1206.                 myPointer = myPointer->fNextEntry;
  1207.             }
  1208.         
  1209.         } while (Q3View_EndRendering(myView) == kQ3ViewStatusRetraverse);
  1210.         
  1211.     // wait until the rendering is completed...
  1212.     Q3View_Sync(myView);
  1213.     
  1214.     return(myStatus);
  1215. }
  1216.  
  1217.  
  1218. //////////
  1219. //
  1220. // VR3DObjects_SubmitModel
  1221. // Submit a QuickDraw 3D model for rendering, picking, bounding, or writing.
  1222. //
  1223. //////////
  1224.  
  1225. TQ3Status VR3DObjects_SubmitModel (VRScript3DObjPtr thePointer, TQ3ViewObject theView)
  1226. {
  1227.     TQ3Vector3D        myTranslate;
  1228.     TQ3Vector3D        myScale;
  1229.  
  1230.     if (thePointer != NULL) {
  1231.         myTranslate = *(TQ3Vector3D *) &(thePointer->fGroupCenter);
  1232.         myScale.x = myScale.y = myScale.z = thePointer->fGroupScale;
  1233.  
  1234.         Q3Style_Submit(thePointer->fInterpolation, theView);
  1235.         Q3Style_Submit(thePointer->fBackFacing, theView);
  1236.         Q3Style_Submit(thePointer->fFillStyle, theView);
  1237.         Q3MatrixTransform_Submit(&(thePointer->fRotation), theView);
  1238.         Q3TranslateTransform_Submit(&myTranslate, theView);
  1239.         Q3ScaleTransform_Submit(&myScale, theView);
  1240.         Q3DisplayGroup_Submit(thePointer->fModel, theView);
  1241.         return(kQ3Success);
  1242.     }
  1243.     
  1244.     return(kQ3Failure);
  1245. }
  1246.  
  1247.  
  1248. //////////
  1249. //
  1250. // VR3DObjects_GetModelFromFile
  1251. // Open a model contained in a 3DMF file.
  1252. //
  1253. //////////
  1254.  
  1255. TQ3GroupObject VR3DObjects_GetModelFromFile (char *thePathName)
  1256. {
  1257.     TQ3StorageObject    myStorage;
  1258.     TQ3GroupObject         myModel;
  1259.     OSErr                myErr = noErr;
  1260.     
  1261. #if TARGET_OS_MAC
  1262.     FSSpec                myFSSpec;
  1263.     short                myRefNum;
  1264.  
  1265.     // for Macintosh, open the file and create a Mac storage object
  1266.     FSMakeFSSpec(0, 0L, c2pstr(thePathName), &myFSSpec);
  1267.     myErr = FSpOpenDF(&myFSSpec, fsRdPerm, &myRefNum);
  1268.     if (myErr == noErr)
  1269.         myStorage = Q3MacintoshStorage_New(myRefNum);
  1270. #endif
  1271.  
  1272. #if TARGET_OS_WIN32
  1273.     // for Windows, create a UNIX pathname storage object (Q3UnixPathStorage_New calls fopen internally)
  1274.     myStorage = Q3UnixPathStorage_New(thePathName);
  1275. #endif    
  1276.     
  1277.     if (myStorage != NULL) {
  1278.         TQ3FileObject        myFile;
  1279.         TQ3Status            myStatus;
  1280.         TQ3Object            myObject;
  1281.         TQ3Boolean            isEOF;
  1282.         
  1283.         // create a file object
  1284.         myFile = Q3File_New();
  1285.         if (myFile == NULL)
  1286.             return(NULL);
  1287.         
  1288.         // associate the storage with the file
  1289.         Q3File_SetStorage(myFile, myStorage);
  1290.         Q3Object_Dispose(myStorage);
  1291.     
  1292.         // read the drawable objects from the file object into a new group
  1293.         myModel = Q3DisplayGroup_New();
  1294.         if (myModel != NULL) {
  1295.             myStatus = Q3File_OpenRead(myFile, NULL);
  1296.             if (myStatus == kQ3Success) {
  1297.             
  1298.                 do {
  1299.                     myObject = Q3File_ReadObject(myFile);
  1300.                     
  1301.                     // if object read is not NULL, then process object
  1302.                     if (myObject != NULL) {
  1303.                         if (Q3Object_IsDrawable(myObject))
  1304.                             Q3Group_AddObject(myModel, myObject);
  1305.                         
  1306.                         Q3Object_Dispose(myObject);
  1307.                     }
  1308.                     
  1309.                     // check to see whether we've reached the end of file yet
  1310.                     isEOF = Q3File_IsEndOfFile(myFile);
  1311.                 } while (isEOF == kQ3False);
  1312.                 
  1313.             }
  1314.         }
  1315.         
  1316.         // close the file object
  1317.         Q3File_Close(myFile);
  1318.     }
  1319.     
  1320.     // apply illumination shader to model
  1321.     myModel = VR3DObjects_CreateDefaultGroup(myModel);
  1322.  
  1323. #if TARGET_OS_MAC
  1324.     // close the file, since we've got the data we need
  1325.     FSClose(myRefNum);
  1326. #endif
  1327.  
  1328. #if TARGET_OS_WIN32
  1329.     // no action required for UNIX pathname storage
  1330. #endif
  1331.  
  1332.     return(myModel);
  1333. }
  1334.  
  1335.  
  1336. ///////////
  1337. //
  1338. // VR3DObjects_PrescreenRoutine
  1339. // Draw the 3D objects into the current graphics world.
  1340. //
  1341. //////////
  1342.  
  1343. void VR3DObjects_PrescreenRoutine (QTVRInstance theInstance, WindowObject theWindowObject)
  1344. {
  1345. #pragma unused(theInstance)
  1346.  
  1347.     ApplicationDataHdl    myAppData;
  1348.     CGrafPtr            myGWorld;
  1349.     GDHandle            myGDevice;
  1350.     PixMapHandle        mySrcPixMap;
  1351.     PixMapHandle        myDstPixMap;
  1352.                 
  1353.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  1354.     if (myAppData == NULL)
  1355.         return;
  1356.  
  1357.     // render any objects into the pixmap draw context
  1358.     VR3DObjects_DrawModel(theWindowObject);
  1359.             
  1360.     // get the current graphics world
  1361.     // (on entry, the current graphics world is set to the prescreen buffer)
  1362.     GetGWorld(&myGWorld, &myGDevice);
  1363.     
  1364.     RGBBackColor(&(**myAppData).fQD3DKeyColor);
  1365.     OpColor(&(**myAppData).fQD3DKeyColor);
  1366.     
  1367.     mySrcPixMap = GetGWorldPixMap((**myAppData).fQD3DDCGWorld);
  1368.     myDstPixMap = GetGWorldPixMap(myGWorld);
  1369.     // we don't need to lock the source pixel map, since it was locked when the draw context was created
  1370.     LockPixels(myDstPixMap);
  1371.     
  1372.     // copy the rendered image to the current graphics world
  1373.     CopyBits((BitMapPtr)(*mySrcPixMap),
  1374.              (BitMapPtr)(*myDstPixMap),
  1375.              &(**myAppData).fQD3DDCGWorld->portRect, 
  1376.              &myGWorld->portRect,
  1377.              srcCopy | transparent, 
  1378.              NULL);
  1379.              
  1380.     UnlockPixels(myDstPixMap);
  1381. }
  1382.  
  1383.  
  1384. //////////
  1385. //
  1386. // VR3DObjects_SetCamera
  1387. // Set the FOV of the 3D camera associated with the specified window object;
  1388. // then set the point-of-interest and the location of the 3D camera.
  1389. //
  1390. //////////
  1391.  
  1392. void VR3DObjects_SetCamera (WindowObject theWindowObject)
  1393. {
  1394.     ApplicationDataHdl        myAppData;
  1395.     TQ3ViewObject            myView;
  1396.     TQ3CameraObject            myCamera;
  1397.     TQ3CameraPlacement        myCameraPos;
  1398.     QTVRInstance            myInstance;
  1399.     
  1400.     if (theWindowObject == NULL)
  1401.         return;
  1402.     
  1403.     // get the QTVR instance associated with the specified window
  1404.     myInstance = (**theWindowObject).fInstance;
  1405.     if (myInstance == NULL)
  1406.         return;
  1407.         
  1408.     // get the view object associated with the specified window
  1409.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);    
  1410.     if (myAppData == NULL)
  1411.         return;
  1412.     myView = (**myAppData).fView;
  1413.  
  1414.     // get the camera associated with the view object
  1415.     Q3View_GetCamera(myView, &myCamera);
  1416.     
  1417.     if (myCamera != NULL) {
  1418.         float                myFOV, myPan, myTilt;
  1419.         TQ3Point3D            myPoint;
  1420.         TQ3Vector3D            myUpVector;
  1421.         
  1422.         // set the camera's field of view
  1423.         myFOV = QTVRGetFieldOfView(myInstance);
  1424.         
  1425.         if ((**myAppData).fQD3DFOVIsVert) {
  1426.             Q3ViewAngleAspectCamera_SetFOV(myCamera, myFOV);
  1427.         } else {
  1428.             float            myRatio;
  1429.             
  1430.             Q3ViewAngleAspectCamera_GetAspectRatio(myCamera, &myRatio);
  1431.             Q3ViewAngleAspectCamera_SetFOV(myCamera, myFOV * myRatio);
  1432.         }
  1433.  
  1434.         // get the camera's current pan and tilt angles
  1435.         myPan = QTVRGetPanAngle(myInstance);
  1436.         myTilt = QTVRGetTiltAngle(myInstance);
  1437.  
  1438.         // calculate the new point-of-interest
  1439.         myPoint.x = sin(myPan) * cos(myTilt) * k3DObjectDistance;
  1440.         myPoint.y = sin(myTilt) * k3DObjectDistance;
  1441.         myPoint.z = cos(myPan) * cos(myTilt) * k3DObjectDistance;
  1442.         
  1443.         // calculate the new up vector of the camera
  1444.         myUpVector.x = -sin(myTilt) * sin(myPan);
  1445.         myUpVector.y = +cos(myTilt);
  1446.         myUpVector.z = -sin(myTilt) * cos(myPan);
  1447.         Q3Vector3D_Normalize(&myUpVector, &myUpVector);
  1448.         
  1449.         Q3Camera_GetPlacement(myCamera, &myCameraPos);
  1450.         myCameraPos.upVector = myUpVector;
  1451.         
  1452.         myCameraPos.pointOfInterest = myPoint;
  1453.         myCameraPos.cameraLocation = kCameraOrigin;
  1454.         Q3Camera_SetPlacement(myCamera, &myCameraPos);
  1455.         
  1456.         // update the QD3D camera
  1457.         Q3View_SetCamera(myView, myCamera);
  1458.         Q3Object_Dispose(myCamera);
  1459.     }
  1460. }
  1461.  
  1462.  
  1463. //////////
  1464. //
  1465. // VR3DObjects_SetCameraAspectRatio
  1466. // Adjust the aspect ratio of the QuickDraw 3D camera based on current window shape.
  1467. //
  1468. //////////
  1469.  
  1470. void VR3DObjects_SetCameraAspectRatio (WindowObject theWindowObject)
  1471. {
  1472.     ApplicationDataHdl                myAppData;
  1473.     TQ3ViewObject                    myView;
  1474.     TQ3CameraObject                    myCamera;
  1475.  
  1476.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);    
  1477.     if (myAppData == NULL)
  1478.         return;
  1479.         
  1480.     // get the window's view and camera objects
  1481.     myView = (**myAppData).fView;
  1482.     Q3View_GetCamera(myView, &myCamera);
  1483.  
  1484.     // adjust the aspect ratio of the camera
  1485.     if (myCamera != NULL) {
  1486.         Rect                        myRect;
  1487.         float                        myRatio;
  1488.     
  1489.         // get the size of the specified window
  1490.         if ((**theWindowObject).fMovie != NULL)
  1491.             GetMovieBox((**theWindowObject).fMovie, &myRect);
  1492.     
  1493.         // calculate the aspect ratio of the movie rectangle
  1494.         myRatio = (float)(myRect.right - myRect.left) / (float)(myRect.bottom - myRect.top);
  1495.  
  1496.         // determine whether QD3D FOV is horizontal or vertical
  1497.         (**myAppData).fQD3DFOVIsVert = (myRatio >= 1.0);
  1498.                 
  1499.         // adjust camera's aspect ratio
  1500.         Q3ViewAngleAspectCamera_SetAspectRatio(myCamera, myRatio);
  1501.         Q3Object_Dispose(myCamera);
  1502.     }
  1503. }
  1504.  
  1505.  
  1506. //////////
  1507. //
  1508. // VR3DObjects_UpdateDrawContext
  1509. // Delete current QD3D draw context and create a new one based on current window size.
  1510. //
  1511. //////////
  1512.  
  1513. void VR3DObjects_UpdateDrawContext (WindowObject theWindowObject)
  1514. {
  1515.     ApplicationDataHdl                myAppData;
  1516.     TQ3ViewObject                    myView;
  1517.     TQ3DrawContextObject            myDrawContext;
  1518.     CGrafPtr                        mySavedPort;
  1519.     GDHandle                        mySavedDevice;
  1520.     Rect                            myRect;
  1521.     OSErr                            myErr = noErr;
  1522.  
  1523.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);    
  1524.     if (myAppData == NULL)
  1525.         return;
  1526.         
  1527.     // lock the application data handle
  1528.     HLock((Handle)myAppData);
  1529.     
  1530.     // get the size of the movie in the specified window
  1531.     if ((**theWindowObject).fMovie != NULL)
  1532.         GetMovieBox((**theWindowObject).fMovie, &myRect);
  1533.     
  1534.     // get the current drawing environment
  1535.     GetGWorld(&mySavedPort, &mySavedDevice);
  1536.  
  1537.     // update the pixmap draw context GWorld: dispose of the existing one and then allocate a new one
  1538.     DisposeGWorld((**myAppData).fQD3DDCGWorld);
  1539.     (**myAppData).fQD3DDCGWorld = NULL;
  1540.     
  1541.     myErr = QTNewGWorld(&(**myAppData).fQD3DDCGWorld, kOffscreenPixelType, &myRect, NULL, NULL, kICMTempThenAppMemory);
  1542.     if (myErr != noErr)
  1543.         goto bail;
  1544.  
  1545.     // get the window's view and draw context objects
  1546.     myView = (**myAppData).fView;
  1547.     Q3View_GetDrawContext(myView, &myDrawContext);
  1548.  
  1549.     // associate the new GWorld with the QD3D draw context
  1550.     if (myDrawContext != NULL) {
  1551.         // get rid of existing draw context    
  1552.         Q3Object_Dispose(myDrawContext);        
  1553.     
  1554.         // create and set new draw context
  1555.         myDrawContext = VR3DObjects_CreateDrawContext((**myAppData).fQD3DDCGWorld);
  1556.         Q3View_SetDrawContext(myView, myDrawContext);
  1557.         Q3Object_Dispose(myDrawContext);
  1558.     }
  1559.     
  1560. bail:
  1561.     // restore the original drawing environment
  1562.     SetGWorld(mySavedPort, mySavedDevice);
  1563.     HUnlock((Handle)myAppData);
  1564. }
  1565.  
  1566.  
  1567. //////////
  1568. //
  1569. // VR3DObjects_DumpEntryMem
  1570. // Release any memory associated with the specified list entry.
  1571. //
  1572. //////////
  1573.  
  1574. void VR3DObjects_DumpEntryMem (VRScript3DObjPtr theEntry)
  1575. {    
  1576.     if (theEntry != NULL) {
  1577.         if (theEntry->fModel)
  1578.             Q3Object_Dispose(theEntry->fModel);
  1579.         if (theEntry->fInterpolation)
  1580.             Q3Object_Dispose(theEntry->fInterpolation);
  1581.         if (theEntry->fBackFacing)
  1582.             Q3Object_Dispose(theEntry->fBackFacing);
  1583.         if (theEntry->fFillStyle)
  1584.             Q3Object_Dispose(theEntry->fFillStyle);
  1585.         VR3DTexture_Delete(theEntry->fTexture);
  1586.     }
  1587. }
  1588.  
  1589. #endif    // QD3D_AVAIL
  1590.